#include "es_pwm30.h"

/*
stm8 pwm库说明

通道号对应GPIO:
ch0-D4 
ch1-A1
ch2-A2
ch3-D1
ch4-C4
ch5-C3
*/

//通道对应dt表,0,1对应ch0...
u16 ch_dt[12] = {0};

//pwm模式记录 ch0对应最低位,1对应motor模式
u8 pwm_mode = 0;

//启动通道
void pwm_EnableChannel(u8 ch)
{
    switch (ch)
    {
    case 0:
        TIM1_SetCompare1(0x3f);
        TIM1_ITConfig(TIM1_IT_CC1, ENABLE);
        break;

    case 1:
        TIM1_SetCompare2(0x3f);
        TIM1_ITConfig(TIM1_IT_CC2, ENABLE);
        break;

    case 2:
        TIM1_SetCompare3(0x3f);
        TIM1_ITConfig(TIM1_IT_CC3, ENABLE);
        break;

    case 3:
        TIM1_SetCompare4(0x3f);
        TIM1_ITConfig(TIM1_IT_CC4, ENABLE);
        break;

    case 4:
        TIM2_SetCompare1(0x3f);
        TIM2_ITConfig(TIM2_IT_CC1, ENABLE);
        break;

    case 5:
        TIM2_SetCompare2(0x3f);
        TIM2_ITConfig(TIM2_IT_CC2, ENABLE);
        break;
    }
}

//关闭通道
void pwm_DisableChannel(u8 ch)
{
    switch (ch)
    {
    case 0:
        TIM1_ITConfig(TIM1_IT_CC1, DISABLE);
        break;

    case 1:
        TIM1_ITConfig(TIM1_IT_CC2, DISABLE);
        break;

    case 2:
        TIM1_ITConfig(TIM1_IT_CC3, DISABLE);
        break;

    case 3:
        TIM1_ITConfig(TIM1_IT_CC4, DISABLE);
        break;

    case 4:
        TIM2_ITConfig(TIM2_IT_CC1, DISABLE);
        break;

    case 5:
        TIM2_ITConfig(TIM2_IT_CC2, DISABLE);
        break;
    }
}

/*
初始化pwm通道
ch-通道号
mode-pwm模式 
*/
void pwm_InitChannel(u8 ch, Pwm_Mode mode)
{
    //记录mode
    if (mode)
    {
        pwm_mode |= 1 << ch;
    }

    //通道初始化
    switch (ch)
    {
    case 0:
        GPIO_Init(GPIOD, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST); //输出GPIO
        //比较器初始化
        TIM1_TimeBaseInit(Timer_Prescaler, TIM1_COUNTERMODE_UP, pwm_period, 0); //此处设置预分频数
        TIM1_SetCompare1(100);                                                  //设置比较器初值
        TIM1_ClearFlag(TIM1_FLAG_CC1);
        TIM1_ITConfig(TIM1_IT_CC1, ENABLE);
        TIM1_Cmd(ENABLE);
        break;

    case 1:
        GPIO_Init(GPIOA, GPIO_PIN_1, GPIO_MODE_OUT_PP_HIGH_FAST);               //输出GPIO
                                                                                //比较器初始化
        TIM1_TimeBaseInit(Timer_Prescaler, TIM1_COUNTERMODE_UP, pwm_period, 0); //此处设置预分频数
        TIM1_SetCompare2(100);                                                  //设置比较器初值
        TIM1_ClearFlag(TIM1_FLAG_CC2);
        TIM1_ITConfig(TIM1_IT_CC2, ENABLE);
        TIM1_Cmd(ENABLE);
        break;

    case 2:
        GPIO_Init(GPIOA, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);               //输出GPIO
                                                                                //比较器初始化
        TIM1_TimeBaseInit(Timer_Prescaler, TIM1_COUNTERMODE_UP, pwm_period, 0); //此处设置预分频数
        TIM1_SetCompare3(100);                                                  //设置比较器初值
        TIM1_ClearFlag(TIM1_FLAG_CC3);
        TIM1_ITConfig(TIM1_IT_CC3, ENABLE);
        TIM1_Cmd(ENABLE);
        break;

    case 3:
        GPIO_Init(GPIOD, GPIO_PIN_1, GPIO_MODE_OUT_PP_HIGH_FAST);               //输出GPIO
                                                                                //比较器初始化
        TIM1_TimeBaseInit(Timer_Prescaler, TIM1_COUNTERMODE_UP, pwm_period, 0); //此处设置预分频数
        TIM1_SetCompare4(100);                                                  //设置比较器初值
        TIM1_ClearFlag(TIM1_FLAG_CC4);
        TIM1_ITConfig(TIM1_IT_CC4, ENABLE);
        TIM1_Cmd(ENABLE);
        break;

    case 4:
        GPIO_Init(GPIOC, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);
        //比较器初始化
        TIM2_TimeBaseInit(Timer2_Prescaler, pwm_period); //TIM2预分频数相对固定
        TIM2_SetCompare1(100);                           //设置比较器初值
        TIM2_ClearFlag(TIM2_FLAG_CC1);
        TIM2_ITConfig(TIM2_IT_CC1, ENABLE);
        TIM2_Cmd(ENABLE);
        break;

    case 5:
        GPIO_Init(GPIOC, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST);
        //比较器初始化
        TIM2_TimeBaseInit(Timer2_Prescaler, pwm_period); //TIM2预分频数相对固定
        TIM2_SetCompare2(100);                           //设置比较器初值
        TIM2_ClearFlag(TIM2_FLAG_CC2);
        TIM2_ITConfig(TIM2_IT_CC2, ENABLE);
        TIM2_Cmd(ENABLE);
        break;
    }
}

/*
设置pwm通道值
ch-通道号
data-pwm值 0-32000
*/
void pwm_SetChannel(u8 ch, u16 data)
{
    u16 val = 0;

    //电机模式
    if (pwm_mode & (1 << ch))
    {
        //高电平时间
        val = (data + Motor_Mode_Rounder) / Motor_Mode_Divisor;
        ch_dt[ch * 2] = val;

        //低电平时间
        ch_dt[ch * 2 + 1] = 32000 / Motor_Mode_Divisor - val;
    }

    //舵机模式
    else
    {
        //高电平时间
        val = (data + Servo_Mode_Rounder) / Servo_Mode_Divisor + (500 / CC_Cycle);
        ch_dt[ch * 2] = val;

        //低电平时间
        ch_dt[ch * 2 + 1] = 20000 / CC_Cycle - val;
    }
}

//通道toggle标志
u8 chToggle = 0;

//TIM1 CC中断
@far @interrupt void TIM1_CC_IRQHandler(void)
{
    u16 cap = 0;

    //CC1
    if (TIM1_GetITStatus(TIM1_IT_CC1) != RESET)
    {
        TIM1_ClearITPendingBit(TIM1_IT_CC1);
        cap = TIM1_GetCapture1();

        if (chToggle & 0x1)
        {
            TIM1_SetCompare1(cap + ch_dt[0]);
            if (ch_dt[0])
                ch0_H();
        }
        else
        {
            TIM1_SetCompare1(cap + ch_dt[1]);
            if (ch_dt[1])
                ch0_L();
        }

        chToggle ^= 0x1; //位取反
    }

    //CC2
    else if (TIM1_GetITStatus(TIM1_IT_CC2) != RESET)
    {
        TIM1_ClearITPendingBit(TIM1_IT_CC2);
        cap = TIM1_GetCapture2();

        if (chToggle & 0x2)
        {
            TIM1_SetCompare2(cap + ch_dt[2]);
            if (ch_dt[2])
                ch1_H();
        }
        else
        {
            TIM1_SetCompare2(cap + ch_dt[3]);
            if (ch_dt[3])
                ch1_L();
        }

        chToggle ^= 0x2; //位取反
    }

    //CC3
    else if (TIM1_GetITStatus(TIM1_IT_CC3) != RESET)
    {
        TIM1_ClearITPendingBit(TIM1_IT_CC3);
        cap = TIM1_GetCapture3();

        if (chToggle & 0x4)
        {
            TIM1_SetCompare3(cap + ch_dt[4]);
            if (ch_dt[4])
                ch2_H();
        }
        else
        {
            TIM1_SetCompare3(cap + ch_dt[5]);
            if (ch_dt[5])
                ch2_L();
        }

        chToggle ^= 0x4; //位取反
    }

    //CC4
    else if (TIM1_GetITStatus(TIM1_IT_CC4) != RESET)
    {
        TIM1_ClearITPendingBit(TIM1_IT_CC4);
        cap = TIM1_GetCapture4();

        if (chToggle & 0x8)
        {
            TIM1_SetCompare4(cap + ch_dt[6]);
            if (ch_dt[6])
                ch3_H();
        }
        else
        {
            TIM1_SetCompare4(cap + ch_dt[7]);
            if (ch_dt[7])
                ch3_L();
        }

        chToggle ^= 0x8; //位取反
    }
}

//TIM2 CC中断
@far @interrupt void TIM2_CC_IRQHandler(void)
{
    u16 cap = 0;

    if (TIM2_GetITStatus(TIM2_IT_CC1) != RESET)
    {
        TIM2_ClearITPendingBit(TIM2_IT_CC1);
        cap = TIM2_GetCapture1();

        if (chToggle & 0x10)
        {
            TIM2_SetCompare1(cap + ch_dt[8]);
            if (ch_dt[8])
                ch4_H();
        }
        else
        {
            TIM2_SetCompare1(cap + ch_dt[9]);
            if (ch_dt[9])
                ch4_L();
        }

        chToggle ^= 0x10;
    }

    else if (TIM2_GetITStatus(TIM2_IT_CC2) != RESET)
    {
        TIM2_ClearITPendingBit(TIM2_IT_CC2);
        cap = TIM2_GetCapture2();

        if (chToggle & 0x20)
        {
            TIM2_SetCompare2(cap + ch_dt[10]);
            if (ch_dt[10])
                ch5_H();
        }
        else
        {
            TIM2_SetCompare2(cap + ch_dt[11]);
            if (ch_dt[11])
                ch5_L();
        }

        chToggle ^= 0x20;
    }
}
